/****************************************************************************
 *
 *  ALi (Shanghai) Corporation, All Rights Reserved. 2007 Copyright (C)
 *
 *  File: media_player.c
 *
 *  Description: This file describes mp3 file operations.
 *
 *  History:
 *      Date        	Author      	Version  		Comment
 *      ====        	======      =======  	=======
 *  1.  2008.11.06  Martin_Xia  	0.0.1  		
 *
 ****************************************************************************/
#include <types.h>
#include <retcode.h>
#include <sys_config.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <bus/sci/sci.h>
#include <hld/hld_dev.h>
#include <osal/osal_timer.h>

#include <api/libc/list.h>
#include <api/libc/time.h>
#include <api/libfs2/dirent.h>
#include <api/libfs2/errno.h>
#include <api/libfs2/fcntl.h>
#include <api/libfs2/stat.h>
#include <api/libfs2/statvfs.h>
#include <api/libfs2/stdio.h>
#include <api/libfs2/unistd.h>

#include <api/libmp/media_player_api.h>
#include "file_list.h"
#include "play_list.h"
#include "quick_sort.h"

/**********************Global  Variables***********************************/


/**********************Internal  Functions***********************************/
/*
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
int check_file_type(FileType type, FileListType file_list_type)
{
	int				result;

	if (!type)
	{
		return 0;
	}

	switch (file_list_type)
	{
		case MUSIC_FILE_LIST:
		{
			result = F_MP3 * F_OGG * F_BYE1;
			break;
		}

		case IMAGE_FILE_LIST:
		{
			result = F_JPG * F_BMP;
			break;
		}

		case VIDEO_FILE_LIST:
		{
			result = F_MPEG * F_MPG;
			break;
		}

		default:
		{
			result = 0;
			break;
		}
	}

	result = result % type;

	return (!result);
	
}
*/
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
int strcmp_c(const char *s1, const char *s2)
{
	int i;
	char c1, c2;

	for (i = 0, c1 = *s1, c2 = *s2; (c1 != '\0') && (c2 != '\0'); i++)
	{
		c1 = *(s1 + i);
		c2 = *(s2 + i);
		if ((c1 >= 'A') && (c1 <='Z')) c1 += 'a' - 'A';
		if ((c2 >= 'A') && (c2 <='Z')) c2 += 'a' - 'A';
		if (c1 != c2) break;
	}

	return (int)c1 - (int)c2;
}

int strcmp_byex(const char *s1, const char *s2)
{
	if((s1== NULL)||(s2 == NULL))
		return 0;

	char kw1[4]={0x58,0x4e,0x42,'\0'};
	char kw2[4]={0x58,0x4e,0x57,'\0'};
	char kw3[4]={0x42,0x54,0x47,'\0'};

	int i = 0;
	for(i=0;i<3;i++)
	{
		kw1[i]--;
		kw2[i]--;
		kw3[i]--;
	}

	char c1 = *s1;
	
	if ((c1 >= 'A') && (c1 <='Z'))
		c1 += 'a' - 'A';

	if(c1 == 'w')
	{
		if(!strcmp_c(s2, "BYE1")) 
		{
			if(!strcmp_c(s1, kw1)) 
				return 1;
		}
		else if(!strcmp_c(s2, "BYE2")) 
		{
			if(!strcmp_c(s1, kw2)) 
				return 1;
		}
		else
			return 0;
	}
	else if(c1== 'a')
	{
		if(!strcmp_c(s2, "BYE3")) 
		{
			if(!strcmp_c(s1, kw3)) 
				return 1;
		}
		else
			return 0;
	}
	else
	{
		return 0;
	}
	return 0;

}


/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE trim_file_list(FileListHandle handle, char* dirpath)
{
	RET_CODE					ret;
	pFileList						pfile_list;

	
	MP_DEBUG("====>>trim_file_list()\n");
	
	pfile_list = (pFileList) handle;
	if ((!dirpath) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====trim_file_list()\n");
		return RET_FAILURE;
	}
	
	pfile_list->dirpath = MALLOC(STRLEN((char *)dirpath)+1);
	if (pfile_list->dirpath ==NULL)
	{
		MP_DEBUG("malloc failed!\n");
		MP_DEBUG("<<====trim_file_list()\n");
		return RET_FAILURE;
	}
	
	STRCPY(pfile_list->dirpath, (char *)dirpath);
	
	pfile_list->sortorder = 0;
	pfile_list->sorttype = 0;

	ret = sort_file_list(pfile_list, SORT_NAME);
	if (ret != RET_SUCCESS)
	{
		MP_DEBUG("sort_file failed!\n");
		MP_DEBUG("<<====trim_file_list()\n");
		return ret;
	}
	
	MP_DEBUG("<<====trim_file_list()\n");
	
	return RET_SUCCESS;
		
}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
void clean_file_list(pFileList pfile_list)
{
	struct list_head			*ptr = NULL, *ptn = NULL;
	pFileListItem				item = NULL;

	MP_DEBUG("====>>clean_file_list()\n");
	
	if (!pfile_list)
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====clean_file_list()\n");
		return;
	}
	
	if(!list_empty(&pfile_list->head))
	{
		list_for_each_safe(ptr, ptn, &pfile_list->head)
		{
			item = list_entry(ptr, FileListItem, listpointer);
			list_del(ptr);
			FREE(item);
		}
	}
	
	list_del(&pfile_list->listpointer);

	FREE(pfile_list->dirpath);
	pfile_list->dirpath = NULL;
	
	pfile_list->filenum = 0;
	pfile_list->dirnum = 0;
	
	INIT_LIST_HEAD(&pfile_list->head);
	INIT_LIST_HEAD(&pfile_list->listpointer);
	
	MP_DEBUG("<<====clean_file_list()\n");
	
	return;

}

/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
void print_file_list(pFileList pfile_list)
{
	struct list_head						*ptr = NULL;
	pFileListItem							item = NULL;
	UINT16								i=0;

	MP_DEBUG("====>>print_file_list()\n");
	
	MP_DEBUG("list_filelist: %s\t there are %d dirs and %d files in list_filelist\n", pfile_list->dirpath, pfile_list->dirnum, pfile_list->filenum);
	list_for_each(ptr, &pfile_list->head)
	{
		item = list_entry(ptr, FileListItem, listpointer);
		if(item != NULL)
		{
			if(item->type == F_DIR)
			{
				MP_DEBUG("FL [DIR] %d\t %s\n", i++, item->name);
			}
			else
			{
				MP_DEBUG("FL [FILE] %d\t %s\n", i++, item->name);
			}
		}
	}

	MP_DEBUG("<<====print_file_list()\n");
	return;
}

/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
pFileListItem	get_file_list_item_by_index(pFileList pfile_list, unsigned short index)
{
	pFileListItem							item = NULL;
	struct list_head						*ptr;

	MP_DEBUG("====>>get_file_list_item_by_index()\n");
	if ((!pfile_list) || ((index<=0) || (index > (pfile_list->dirnum+pfile_list->filenum))))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====get_file_list_item_by_index()\n");
		return item;
	}
	
/*
	if(filelist->sortorder)
	{
		if (idx > filelist->dirnum)
		{
			idx -= filelist->dirnum;
			idx = filelist->dirnum+filelist->filenum+1-idx;
		}
	}
*/

	if((index*2) > (pfile_list->dirnum+pfile_list->filenum))
	{
		index = pfile_list->dirnum+pfile_list->filenum+1-index;
		list_for_each_prev(ptr, &pfile_list->head)
		{
			if(!--index)
			{
				item = list_entry(ptr, FileListItem, listpointer);
				break;
			}
		}
	}
	else
	{
		list_for_each(ptr, &pfile_list->head)
		{
			if(!--index)
			{
				item = list_entry(ptr, FileListItem, listpointer);
				break;
			}
		}
	}

	MP_DEBUG("<<====get_file_list_item_by_index()\n");
	
	return item;
}


/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
int compare_file_list_items(struct list_head *p1, struct list_head *p2, struct CompareParameter *p_para)
{
	char												*c1, *c2;
	char												*p_ctemp;
	char												t1,t2;
	int												temp1, temp2;
	unsigned int										s1,s2;
	pFileListCompareContext							compare_para;


	compare_para = (pFileListCompareContext)p_para->context;
	
	if (compare_para->id_check_playlist == 0)
	{
		switch(compare_para->mode)
		{
			case SORT_FAV:
			{
				t1 = list_entry(p1, FileListItem, listpointer)->in_play_list;
				t2 = list_entry(p2, FileListItem, listpointer)->in_play_list;
				if (t1 != t2)
				{
					return (int)(t2 - t1); 
				}
				
			}
			
			case SORT_NAME:
			{
				c1 = list_entry(p1, FileListItem, listpointer)->name;
				c2 = list_entry(p2, FileListItem, listpointer)->name;
				
				while ((*c1 != '\0') && (*c2 != '\0'))
				{
					if (*c1 != *c2) 
					{
						break;
					}
					c1++;
					c2++;
				}
				return (int)((unsigned char)(*c1)) - (int)((unsigned char)(*c2));
			}
/*
			case SORT_NAME_Z_A:
			{
				c1 = list_entry(p1, FileListItem, listpointer)->name;
				c2 = list_entry(p2, FileListItem, listpointer)->name;
				
				while ((*c1 != '\0') && (*c2 != '\0'))
				{
					if (*c1 != *c2) 
					{
						break;
					}
					c1++;
					c2++;
				}
				return (int)((unsigned char)(*c2)) - (int)((unsigned char)(*c1));
			}
*/
			case SORT_DATE:
			{
				s1 = list_entry(p1, FileListItem, listpointer)->time;
				s2 = list_entry(p2, FileListItem, listpointer)->time;

				return (int)(s1-s2);
			}

			case SORT_SIZE:
			{
				s1 = list_entry(p1, FileListItem, listpointer)->size;
				s2 = list_entry(p2, FileListItem, listpointer)->size;

                if(s1>s2)
                {
                    return 1;
                }
                else if(s1<s2)
                {
                    return -1;
                }
                else
                {
                    return 0;
                }
				//return (int)(s1-s2);
			}
			
			default:
			{
				return 0;
			}
		}
	}

	return 0;
}
/**********************External  Functions***********************************/

/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
FileListHandle create_file_list(FileListType type)
{
	pFileList						pfile_list = NULL;

	MP_DEBUG("====>>trim_file_list()\n");

	if ((type>=MEDIA_PLAYER_FILE_LIST_NUMBER) /*|| (type<MUSIC_FILE_LIST)*/)
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====create_file_list()\n");
		return NULL;
	}


	pfile_list = (pFileList) MALLOC(sizeof(FileList));
	if (!pfile_list)
	{
		MP_DEBUG("malloc failed!\n");
		MP_DEBUG("<<====create_file_list()\n");
		return NULL;
	}

	MEMSET(pfile_list, 0, sizeof(FileList));

	INIT_LIST_HEAD(&pfile_list->head);
	INIT_LIST_HEAD(&pfile_list->listpointer);

	pfile_list->type = type;
	
	MP_DEBUG("<<====create_file_list()\n");
	
	return (FileListHandle)pfile_list;
		
}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
void delete_file_list(FileListHandle handle)
{
	struct list_head			*ptr = NULL, *ptn = NULL;
	pFileListItem				item = NULL;
	pFileList					pfile_list;
	
	MP_DEBUG("====>>file_list_delete()\n");

	pfile_list = (pFileList) handle;
	if (!pfile_list)
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====file_list_delete()\n");
		return;
	}
	
	if(!list_empty(&pfile_list->head))
	{
		list_for_each_safe(ptr, ptn, &pfile_list->head)
		{
			item = list_entry(ptr, FileListItem, listpointer);
			list_del(ptr);
			FREE(item);
		}
	}
	
	list_del(&pfile_list->listpointer);
	FREE(pfile_list->dirpath);
	
	FREE(pfile_list);
	
	MP_DEBUG("<<====file_list_delete()\n");
	
	return;
}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE file_list_change_device(FileListHandle handle, char* devicename)
{
	FileType						file_type = F_DIR;	
	pFileListItem					pfile_list_item = NULL;
	unsigned int					start_time, end_time;
	unsigned int					entry_count = 0;
	pFileList						pfile_list;
	int							dirfd;
	struct dirent*					entry;
	char							buff[sizeof(struct dirent) + MAX_FILE_NAME_SIZE];

	struct list_head *ptr = NULL, *ptn = NULL, dir_head, file_head;
	
	MP_DEBUG("====>>file_list_change_device()\n");

	pfile_list = (pFileList) handle;
	if ((!devicename) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====file_list_change_device()\n");
		return RET_FAILURE;
	}

	
	if ((dirfd = fs_opendir(FS_ROOT_DIR)) < 0) 
	{
		libc_printf( "dir: error opening: %s\n", FS_ROOT_DIR);
		MP_DEBUG("<<====file_list_change_device()\n");
		return RET_FAILURE;
	}
	
	entry = (struct dirent *)buff;
	
	clean_file_list(pfile_list);
	
	start_time = osal_get_tick();
	
	while (1)
	{
		if (fs_readdir(dirfd, entry) <= 0)
		{
			break;
		}
		
		if (S_ISDIR(entry->d_type)) //dir
		{
			//the items under the FS_ROOT_DIR can only be dirs
			if (strncmp(entry->d_name, devicename, 3)) // a disk is identified by 3 char, eg. "uda"
			{
				continue;	
			}
						
			pfile_list_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(entry->d_name) + 1);
			if (pfile_list_item == NULL)
			{
				break;
			}
			
			MEMSET(pfile_list_item, 0, sizeof(FileListItem));

			pfile_list_item->type = F_DIR;
			
			STRCPY(pfile_list_item->name, entry->d_name);

			pfile_list->dirnum++;

			list_add(&pfile_list_item->listpointer, &pfile_list->head);
			
			entry_count++;
			if (entry_count >= MAX_FILE_NUMBER) 
			{
				break;
			}
			
		}
		
	}

	
	fs_closedir(dirfd);
	
	start_time = osal_get_tick();
	if( trim_file_list(pfile_list, FS_ROOT_DIR) != RET_SUCCESS)
	{
		MP_DEBUG("trim_file_list() failed!\n");
		MP_DEBUG("<<====file_list_change_device()\n");
		return RET_FAILURE;
	}
	end_time = osal_get_tick();

	
	MP_DEBUG("create filelist takes time %d ms\n", end_time-start_time);
	
	MP_DEBUG("<<====file_list_change_device()\n");
	
	return RET_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE read_folder_to_file_list(FileListHandle handle, char *dirpath)
{
	FileType						file_type;
	FileListType					type;
	struct dirent					*items = NULL;
	pFileListItem					pfile_list_item = NULL;
	unsigned int					start_time, end_time;
	unsigned int					entry_cnt = 0;
	pFileList						pfile_list;
	int							dirfd;
	struct dirent					*entry;
	char							buff[sizeof(struct dirent) + MAX_FILE_NAME_SIZE];
	struct stat					file_attribute;
	int							ret;
	char							full_path[FULL_PATH_SIZE];
	int							dirpath_length;

	MP_DEBUG("====>>read_folder_to_file_list()\n");	

	pfile_list = (pFileList) handle;
	if ((!dirpath) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====read_folder_to_file_list()\n");
		return RET_FAILURE;
	}

	type = pfile_list->type;

	MEMSET(full_path, 0, FULL_PATH_SIZE);
	STRCPY(full_path, dirpath);
	strcat(full_path, "/");
	dirpath_length = STRLEN(dirpath) + 1;
	
	if ((dirfd = fs_opendir(dirpath)) < 0)
	{
		libc_printf( "dir: error opening: %s\n", dirpath);
		MP_DEBUG("<<====read_folder_to_file_list()\n");
		return RET_FAILURE;
	}
	
	entry = (struct dirent *)buff;
	
	clean_file_list(pfile_list);
	
	start_time = osal_get_tick();
	
	while (1)
	{
		if (fs_readdir(dirfd, entry) <= 0)
		{
			break;
		}
		
		if (S_ISDIR(entry->d_type)) //dir
		{
			if (!STRCMP(entry->d_name, "."))
			{
				continue;
			}
			
			if (!STRCMP(entry->d_name, ".."))
			{
				continue;
			}
			
			if (!strcmp_c(entry->d_name, "ALiDvr"))
			{
				continue;
			}
			if (!strcmp_c(entry->d_name, "ALIDVRS2"))
			{
				continue;
			}			
			/*
			if (!strcmp_c(entry->d_name, udisk_filter))
			{
				continue;
			}
			*/
			if (!strcmp_c(entry->d_name, "recycler"))
			{
				continue;
			}
			
			if (!strcmp_c(entry->d_name, "system volume information"))
			{
				continue;
			}
			
			pfile_list_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(entry->d_name) + 1);
			if (pfile_list_item == NULL)
			{
				break;
			}
			
			MEMSET(pfile_list_item, 0, sizeof(FileListItem));

			pfile_list_item->type = F_DIR;
			
			STRCPY(pfile_list_item->name, entry->d_name);

			pfile_list->dirnum++;

			list_add(&pfile_list_item->listpointer, &pfile_list->head);
		}
		else //file
		{
			int j, k;
			for (j = 0, k = -1; entry->d_name[j] != '\0'; j++)
			{
				if (entry->d_name[j] == '.') k = j;
			}
			if (k == -1)
			{
				continue;
			}
			else
			{
				k++;
				
				file_type = F_UNKOWN;
				
				if (type == MUSIC_FILE_LIST)
				{
					if(!strcmp_c(entry->d_name + k, "MP3"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "MP2"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "MP1"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "MPA"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "OGG"))
					{
						file_type = F_OGG;
					}
                    else if(!strcmp_c(entry->d_name + k, "AAC"))
                    {
                        file_type = F_MP3;
                    }
                    else if(!strcmp_c(entry->d_name + k, "AC3"))
                    {
                        file_type = F_MP3;
                    }
#ifdef MEDIA_PLAYER_BYE1_SUPPORT					
					else if(strcmp_byex(entry->d_name + k, "BYE1"))
					{
						file_type = F_BYE1;
					}
#endif					
                    else if(!strcmp_c(entry->d_name + k, "WAV"))          
    				{
    					file_type = F_MP3;
    				}
                    else if(!strcmp_c(entry->d_name + k, "FLAC"))         // support FLAC file Ivan 2012/9/19
    				{
    					file_type = F_FLC;																					
    				}
				}
				else if (type == IMAGE_FILE_LIST)
				{
					if(!strcmp_c(entry->d_name + k, "JPG"))
					{
						file_type = F_JPG;
					}
                    else if(!strcmp_c(entry->d_name + k, "JPEG"))
					{
						file_type = F_JPG;
					}
					else if(!strcmp_c(entry->d_name + k, "BMP"))
					{
						file_type = F_BMP;
					}
				#ifdef PNG_GIF_TEST
					else if(!strcmp_c(entry->d_name + k, "GIF"))
					{
						file_type = F_BMP;
					}
					else if(!strcmp_c(entry->d_name + k, "PNG"))
					{
						file_type = F_BMP;
					}
				#endif
				}
#ifdef MEDIA_PLAYER_VIDEO_SUPPORT
				else if (type == VIDEO_FILE_LIST)
				{
					if(!strcmp_c(entry->d_name + k, "MPG"))
					{
						 file_type = F_MPG;
					}
					else if(!strcmp_c(entry->d_name + k, "MPEG"))
					{
						file_type = F_MPEG;
					}
                    else if(!strcmp_c(entry->d_name + k, "DAT"))
					{
						file_type = F_MPEG;
					}
#ifdef SUPPORT_MPEG4_TEST
				#ifndef _S3281_	
					else if(!strcmp_c(entry->d_name + k, "VOB"))
					{
						file_type = F_MPEG;
					}
    				else if(!strcmp_c(entry->d_name + k, "AVI"))
    				{
    				    file_type = F_MPG;
    				}
#endif
                    else if(!strcmp_c(entry->d_name + k, "TS"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "TRP"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "TP"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "M2T"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "M2TS"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "MTS"))
                    {
                        file_type = F_MPG;
                    }
				#ifndef _S3281_		
                    else if(!strcmp_c(entry->d_name + k, "MP4"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "MKV"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "MOV"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "3GP"))
                    {
                        file_type = F_MPG;
                    }
                    else if(strcmp_byex(entry->d_name + k, "BYE2"))//'X'='W'+1  'N'='M'+1  'W'='V'+1
                    {
                        file_type = F_MPG;
                    }
		    		else if(!strcmp_c(entry->d_name + k, "FLV"))
                    {
                        file_type = F_MPG;
                    }
					else if(!strcmp_c(entry->d_name + k, "RMVB"))
					{
						file_type = F_MPG;
					}
					else if(!strcmp_c(entry->d_name + k, "RM"))
					{
						file_type = F_MPG;
					}
					else if(!strcmp_c(entry->d_name + k, "RAM"))
					{
						file_type = F_MPG;
					}
                #ifdef _S3811_
					else if(!strcmp_c(entry->d_name + k, "WEBM"))
					{
						file_type = F_MPG;
					}
                #endif
				#endif
#ifdef SUPPORT_ES_PLAYER
			else if(!strcmp_c(entry->d_name + k, "ES"))	
			{
				file_type = F_MPG;
			}				
#endif
#endif
				}
#endif				
				if (file_type == F_UNKOWN)
				{
					continue;
				}

				pfile_list_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(entry->d_name) + 1);
				if (pfile_list_item == NULL)
				{
					break;
				}
				
				MEMSET(pfile_list_item, 0, sizeof(FileListItem));

				pfile_list_item->type = file_type;

				STRCPY((full_path + dirpath_length), entry->d_name);
				ret = fs_stat(full_path, &file_attribute);
				if (ret >= 0)
				{
					pfile_list_item->size = file_attribute.st_size;
					pfile_list_item->time = file_attribute.st_ctime;
					struct tm		mmtime;
					gmtime_r(&file_attribute.st_ctime, &mmtime);
					MP_DEBUG("year = %d, month = %d, day = %d\n", mmtime.tm_year+1900, mmtime.tm_mon+1, mmtime.tm_mday+1);
					//pfile_list_item-> = ;
				}
				
				STRCPY(pfile_list_item->name, entry->d_name);

				pfile_list->filenum++;

				list_add_tail(&pfile_list_item->listpointer, &pfile_list->head);
			}
		}
		
		
		entry_cnt++;

		if (entry_cnt >= MAX_FILE_NUMBER)
		{
			break;
		}
		
	}

	//MP_DEBUG("read entries in directory \"%s\" takes %d ms\n", dirpath, osal_get_tick() - start_time);
	
	fs_closedir(dirfd);
	
	start_time = osal_get_tick();
	if(trim_file_list(pfile_list, dirpath) == RET_SUCCESS)
	{
		MP_DEBUG("trim_file_list() failed!\n");	
		MP_DEBUG("<<====read_folder_to_file_list()\n");	
		return RET_FAILURE;
	}
	end_time = osal_get_tick();
	
	MP_DEBUG("create filelist takes time %d ms\n", end_time-start_time);
	
	MP_DEBUG("<<====read_folder_to_file_list()\n");	
	
	return RET_SUCCESS;
}

/*******************************************
read_folder_to_file_list2 optimize the time of read the whole dir.
if the dir has many file,but func fs_stat consumes too much time.
so we delay to get file attribute.
we read file attribute in the func get_file_from_file_list2.
*******************************************/
RET_CODE read_folder_to_file_list2(FileListHandle handle, char *dirpath)
{
	FileType						file_type;
	FileListType					type;
	struct dirent					*items = NULL;
	pFileListItem					pfile_list_item = NULL;
	unsigned int					start_time, end_time;
	unsigned int					entry_cnt = 0;
	pFileList						pfile_list;
	int							dirfd;
	struct dirent					*entry;
	char							buff[sizeof(struct dirent) + MAX_FILE_NAME_SIZE];
	struct stat					file_attribute;
	int							ret;
	char							full_path[FULL_PATH_SIZE];
	int							dirpath_length;

	MP_DEBUG("====>>read_folder_to_file_list()\n");	

	pfile_list = (pFileList) handle;
	if ((!dirpath) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====read_folder_to_file_list()\n");
		return RET_FAILURE;
	}

	type = pfile_list->type;
	//static UINT32 start_tick = 0;
	//start_tick = osal_get_tick();

	MEMSET(full_path, 0, FULL_PATH_SIZE);
	STRCPY(full_path, dirpath);
	strcat(full_path, "/");
	dirpath_length = STRLEN(dirpath) + 1;
	
	if ((dirfd = fs_opendir(dirpath)) < 0)
	{
		libc_printf( "dir: error opening: %s\n", dirpath);
		MP_DEBUG("<<====read_folder_to_file_list()\n");
		return RET_FAILURE;
	}
	
	entry = (struct dirent *)buff;
	
	clean_file_list(pfile_list);
	
	start_time = osal_get_tick();
	//libc_printf("%s(%d) : read_folder_to_file_list < %d > \n ",__FUNCTION__,__LINE__,osal_get_tick() - start_time);
	
	while (1)
	{
		//start_time = osal_get_tick();
		if (fs_readdir(dirfd, entry) <= 0)
		{
			break;
		}
		//libc_printf("%s(%d) : read_folder_to_file_list < %d > \n ",__FUNCTION__,__LINE__,osal_get_tick() - start_time);
		
		if (S_ISDIR(entry->d_type)) //dir
		{
			//start_time = osal_get_tick();
			if (!STRCMP(entry->d_name, "."))
			{
				continue;
			}
			
			if (!STRCMP(entry->d_name, ".."))
			{
				continue;
			}
			
			if (!strcmp_c(entry->d_name, "ALiDvr"))
			{
				continue;
			}
			if (!strcmp_c(entry->d_name, "ALIDVRS2"))
			{
				continue;
			}			
			/*
			if (!strcmp_c(entry->d_name, udisk_filter))
			{
				continue;
			}
			*/
			if (!strcmp_c(entry->d_name, "recycler"))
			{
				continue;
			}
			
			if (!strcmp_c(entry->d_name, "system volume information"))
			{
				continue;
			}
			
			pfile_list_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(entry->d_name) + 1);
			if (pfile_list_item == NULL)
			{
				break;
			}
			
			MEMSET(pfile_list_item, 0, sizeof(FileListItem));

			pfile_list_item->type = F_DIR;
			
			STRCPY(pfile_list_item->name, entry->d_name);

			pfile_list->dirnum++;

			list_add(&pfile_list_item->listpointer, &pfile_list->head);
			//libc_printf("%s(%d) : read_folder_to_file_list < %d > \n ",__FUNCTION__,__LINE__,osal_get_tick() - start_time);
		}
		else //file
		{
			//start_time = osal_get_tick();
			int j, k;
			for (j = 0, k = -1; entry->d_name[j] != '\0'; j++)
			{
				if (entry->d_name[j] == '.') k = j;
			}
			if (k == -1)
			{
				continue;
			}
			else
			{
				k++;
				
				file_type = F_UNKOWN;
				
				if (type == MUSIC_FILE_LIST)
				{
					if(!strcmp_c(entry->d_name + k, "MP3"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "MP2"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "MP1"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "MPA"))
					{
						file_type = F_MP3;
					}
					else if(!strcmp_c(entry->d_name + k, "OGG"))
					{
						file_type = F_OGG;
					}
                    else if(!strcmp_c(entry->d_name + k, "AAC"))
                    {
                        file_type = F_MP3;
                    }
                    else if(!strcmp_c(entry->d_name + k, "AC3"))
                    {
                        file_type = F_MP3;
                    }
#ifdef MEDIA_PLAYER_BYE1_SUPPORT					
					else if(strcmp_byex(entry->d_name + k, "BYE1"))
					{
						file_type = F_BYE1;
					}
#endif					
                    else if(!strcmp_c(entry->d_name + k, "WAV"))          
    				{
    					file_type = F_MP3;
    				}
                    else if(!strcmp_c(entry->d_name + k, "FLAC"))         // support FLAC file Ivan 19/9/2011
    				{
    					file_type = F_FLC;
    				}
				}
				else if (type == IMAGE_FILE_LIST)
				{
					if(!strcmp_c(entry->d_name + k, "JPG"))
					{
						file_type = F_JPG;
					}
                    else if(!strcmp_c(entry->d_name + k, "JPEG"))
					{
						file_type = F_JPG;
					}
					else if(!strcmp_c(entry->d_name + k, "BMP"))
					{
						file_type = F_BMP;
					}
				#ifdef PNG_GIF_TEST
					else if(!strcmp_c(entry->d_name + k, "GIF"))
					{
						file_type = F_BMP;
					}
					else if(!strcmp_c(entry->d_name + k, "PNG"))
					{
						file_type = F_BMP;
					}
				#endif
				}
#ifdef MEDIA_PLAYER_VIDEO_SUPPORT
				else if (type == VIDEO_FILE_LIST)
				{
					if(!strcmp_c(entry->d_name + k, "MPG"))
					{
						 file_type = F_MPG;
					}
					else if(!strcmp_c(entry->d_name + k, "MPEG"))
					{
						file_type = F_MPEG;
					}
                    else if(!strcmp_c(entry->d_name + k, "DAT"))
					{
						file_type = F_MPEG;
					}
#ifdef SUPPORT_MPEG4_TEST
				#ifndef _S3281_	
					else if(!strcmp_c(entry->d_name + k, "VOB"))
					{
						file_type = F_MPEG;
					}
    				else if(!strcmp_c(entry->d_name + k, "AVI"))
    				{
    				    file_type = F_MPG;
    				}
#endif
                    else if(!strcmp_c(entry->d_name + k, "TS"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "TRP"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "TP"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "M2T"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "M2TS"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "MTS"))
                    {
                        file_type = F_MPG;
                    }
				#ifndef _S3281_		
                    else if(!strcmp_c(entry->d_name + k, "MP4"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "MKV"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "MOV"))
                    {
                        file_type = F_MPG;
                    }
                    else if(!strcmp_c(entry->d_name + k, "3GP"))
                    {
                        file_type = F_MPG;
                    }
                    else if(strcmp_byex(entry->d_name + k, "BYE2"))//'X'='W'+1  'N'='M'+1  'W'='V'+1
                    {
                        file_type = F_MPG;
                    }
		    		else if(!strcmp_c(entry->d_name + k, "FLV"))
                    {
                        file_type = F_MPG;
                    }
					else if(!strcmp_c(entry->d_name + k, "RMVB"))
					{
						file_type = F_MPG;
					}
					else if(!strcmp_c(entry->d_name + k, "RM"))
					{
						file_type = F_MPG;
					}
					else if(!strcmp_c(entry->d_name + k, "RAM"))
					{
						file_type = F_MPG;
					}
					else if(!strcmp_c(entry->d_name + k, "WEBM"))
					{
						file_type = F_MPG;
					}
				#endif
#ifdef SUPPORT_ES_PLAYER
			else if(!strcmp_c(entry->d_name + k, "ES"))	
			{
				file_type = F_MPG;
			}				
#endif
#endif
				}
#endif				
				if (file_type == F_UNKOWN)
				{
					continue;
				}

				pfile_list_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(entry->d_name) + 1);
				if (pfile_list_item == NULL)
				{
					break;
				}
				
				MEMSET(pfile_list_item, 0, sizeof(FileListItem));

				pfile_list_item->type = file_type;

				STRCPY((full_path + dirpath_length), entry->d_name);
				//ret = fs_stat(full_path, &file_attribute);
				//libc_printf("%s(%d) : read_folder_to_file_list < %d > \n ",__FUNCTION__,__LINE__,osal_get_tick() - start_time);
				//if (ret >= 0)
				{
					//pfile_list_item->size = 0;//file_attribute.st_size;
					//pfile_list_item->time = 0x;//file_attribute.st_ctime;
					//struct tm		mmtime;
					//gmtime_r(&file_attribute.st_ctime, &mmtime);
					//MP_DEBUG("year = %d, month = %d, day = %d\n", mmtime.tm_year+1900, mmtime.tm_mon+1, mmtime.tm_mday+1);
					//pfile_list_item-> = ;
				}
				
				STRCPY(pfile_list_item->name, entry->d_name);

				pfile_list->filenum++;

				list_add_tail(&pfile_list_item->listpointer, &pfile_list->head);
				//libc_printf("%s(%d) : read_folder_to_file_list < %d > \n ",__FUNCTION__,__LINE__,osal_get_tick() - start_time);
			}
		}
		
		
		entry_cnt++;

		if (entry_cnt >= MAX_FILE_NUMBER)
		{
			break;
		}
		
	}

	//MP_DEBUG("read entries in directory \"%s\" takes %d ms\n", dirpath, osal_get_tick() - start_time);
	//start_time = osal_get_tick();
	fs_closedir(dirfd);
	//libc_printf("%s(%d) : read_folder_to_file_list < %d > \n ",__FUNCTION__,__LINE__,osal_get_tick() - start_time);
	
	
	//start_time = osal_get_tick();
	if(trim_file_list(pfile_list, dirpath) == RET_SUCCESS)
	{
		MP_DEBUG("trim_file_list() failed!\n");	
		MP_DEBUG("<<====read_folder_to_file_list()\n");	
		return RET_FAILURE;
	}
	end_time = osal_get_tick();
	
	MP_DEBUG("create filelist takes time %d ms\n", end_time-start_time);
	
	MP_DEBUG("<<====read_folder_to_file_list()\n");	
	
	libc_printf("%s(%d) : read_folder_to_file_list < %d > \n ",__FUNCTION__,__LINE__,osal_get_tick() - start_time);
	return RET_SUCCESS;
}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
void check_files_in_play_list(FileListHandle handle, PlayListHandle play_list_handle, char *if_all_in_play_list)
{
	pFileList									pfile_list;
	pPlayList									pplay_list;
	struct list_head							*file_list_ptr = NULL, *file_list_ptn = NULL;
	struct list_head							*play_list_ptr = NULL, *play_list_ptn = NULL;
	pFileListItem								file_list_item;
	pPlayListItem								play_list_item;
	char										full_path[FULL_PATH_SIZE];

	MP_DEBUG("====>>check_files_in_play_list()\n");

	if (if_all_in_play_list)
	{
		*if_all_in_play_list = 0;
	}
	
	pfile_list = (pFileList) handle;
	pplay_list = (pPlayList) play_list_handle;
	if ((!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====check_files_in_play_list()\n");
		return;
	}


	if (list_empty(&pfile_list->head))
	{
		MP_DEBUG("file list empty, return!\n");
		MP_DEBUG("<<====check_files_in_play_list()\n");
		return;		
	}

	list_for_each_safe(file_list_ptr, file_list_ptn, &pfile_list->head)
	{
		file_list_item= list_entry(file_list_ptr, FileListItem, listpointer);

		file_list_item->in_play_list = 0;
	}

	if ((!pplay_list))
	{
		MP_DEBUG("Invalid play list Parameters!\n");
		MP_DEBUG("<<====check_files_in_play_list()\n");
		return;
	}

	if (!list_empty(&pplay_list->head))
	{
		if (if_all_in_play_list)
		{
			*if_all_in_play_list = 1;
		}

		list_for_each_safe(file_list_ptr, file_list_ptn, &pfile_list->head)
		{
			file_list_item= list_entry(file_list_ptr, FileListItem, listpointer);

			if (file_list_item->type == F_DIR)
			{
				continue;
			}

			MEMSET(full_path, 0, FULL_PATH_SIZE);
			STRCPY(full_path, pfile_list->dirpath);
			strcat(full_path, "/");
			strcat(full_path, file_list_item->name);
			
			list_for_each_safe(play_list_ptr, play_list_ptn, &pplay_list->head)
			{
				play_list_item = list_entry(play_list_ptr, PlayListItem, listpointer);
				if (!STRCMP(full_path, play_list_item->name))
				{
					file_list_item->in_play_list = 1;
					break;
				}
			}

			if (!file_list_item->in_play_list)
			{
				if (if_all_in_play_list)
				{
					*if_all_in_play_list = 0;
				}
			}
		}
	}
	
	MP_DEBUG("<<====check_files_in_play_list()\n");
}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE sort_file_list(FileListHandle handle, FileListSortType sort_type)
{
	pFileListItem								item;
	struct CompareParameter					para;
	FileListCompareContext						compare_para;
	UINT16									i;
	UINT32									start_time, end_time;
	struct list_head 							*left=NULL, *right=NULL;
	pFileList									pfile_list;
	
	MP_DEBUG("====>>sort_file_list()\n");
	
	pfile_list = (pFileList) handle;
	if ((!pfile_list) || (/*(sort_type<SORT_RAND) ||*/(sort_type>SORT_FAV)))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====sort_file_list()\n");
		return RET_FAILURE;
	}
/*
	if (pfile_list->sorttype == sort_type)
	{
		pfile_list->sortorder = !pfile_list->sortorder;
	}
	else
	{
*/	
		pfile_list->sorttype = sort_type;
		pfile_list->sortorder = 0;
		
		start_time = osal_get_tick();

		compare_para.id_check_playlist = 0;
		compare_para.mode = pfile_list->sorttype;
		para.context = &compare_para;
		para.compare = compare_file_list_items;
		if(pfile_list->dirnum > 1)
		{
			//sort dir
			left = pfile_list->head.next;
			item = get_file_list_item_by_index(pfile_list, pfile_list->dirnum);
			if(item == NULL)
			{
				return RET_FAILURE;
			}
			right = &item->listpointer;
			if (quick_sort_list(left, right, &para) != 0)
			{
				libc_printf("quick sorting filelist failed\n");
			}
		}
		
		if(pfile_list->filenum > 1)
		{
			//sort file
			item = get_file_list_item_by_index(pfile_list, pfile_list->dirnum+1);
			if(item == NULL)
			{
				return RET_FAILURE;
			}
			left = &item->listpointer;
			right = pfile_list->head.prev;
			if (quick_sort_list(left, right, &para) != 0)
			{
				libc_printf("quick sorting filelist failed\n");
			}
		}
		
		end_time = osal_get_tick();
		MP_DEBUG("sort filelist takes time %d ms\n", end_time-start_time);

		//print_file_list(pfile_list);
		
	//}

	
	MP_DEBUG("<<====sort_file_list()\n");
	
	return RET_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE 	get_file_list_info(FileListHandle handle, unsigned int *dir_number, unsigned int *file_number, char* current_path)
{
	pFileList								pfile_list;
	
	MP_DEBUG("====>>get_file_list_info()\n");

	pfile_list = (pFileList) handle;
	if (!pfile_list)
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====get_file_list_info()\n");
		return RET_FAILURE;
	}

	if (dir_number)
	{
		*dir_number = pfile_list->dirnum;
	}

	if (file_number)
	{
		*file_number = pfile_list->filenum;
	}

	if (current_path)
	{
		STRCPY(current_path, pfile_list->dirpath);
	}
	
	MP_DEBUG("<<====get_file_list_info()\n");
	
	return RET_SUCCESS;

}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE 	get_file_from_file_list(FileListHandle handle, unsigned short index, pFileInfo pinfo)
{
	pFileListItem						item;
	pFileList							pfile_list;
	
	MP_DEBUG("====>>get_file_from_file_list()\n");
	
	pfile_list = (pFileList) handle;
	if ((!pinfo)  || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====get_file_from_file_list()\n");
		return RET_FAILURE;
	}

	
	if (index > (pfile_list->dirnum + pfile_list->filenum))
	{
		MP_DEBUG("Invalid Index!\n");
		MP_DEBUG("<<====get_file_from_file_list()\n");
		return RET_FAILURE;
	}
		
	
	item = get_file_list_item_by_index(pfile_list, index);
	if(item == NULL)
	{
		MP_DEBUG("<<====get_file_from_file_list()\n");
		return RET_FAILURE;
	}
		
	pinfo->filetype = item->type;
	pinfo->in_play_list = item->in_play_list;
	pinfo->size = item->size;
	STRCPY(pinfo->path, pfile_list->dirpath);
	STRCPY(pinfo->name, item->name);
	MP_DEBUG("get file: idx=%d\t name=%s\n", index, pinfo->name);

	MP_DEBUG("<<====get_file_from_file_list()\n");
	
	return RET_SUCCESS;
}


/*******************************************
we read file attribute in the func get_file_from_file_list2.
because when we should show the item ,we call the func.
*******************************************/

RET_CODE 	get_file_from_file_list2(FileListHandle handle, unsigned short index, pFileInfo pinfo)
{
	pFileListItem						item;
	pFileList							pfile_list;
	
	MP_DEBUG("====>>get_file_from_file_list()\n");
	
	pfile_list = (pFileList) handle;
	if ((!pinfo)  || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====get_file_from_file_list()\n");
		return RET_FAILURE;
	}

	
	if (index > (pfile_list->dirnum + pfile_list->filenum))
	{
		MP_DEBUG("Invalid Index!\n");
		MP_DEBUG("<<====get_file_from_file_list()\n");
		return RET_FAILURE;
	}
		
	
	item = get_file_list_item_by_index(pfile_list, index);
	if(item == NULL)
	{
		MP_DEBUG("<<====get_file_from_file_list()\n");
		return RET_FAILURE;
	}
		
	pinfo->filetype = item->type;
	pinfo->in_play_list = item->in_play_list;
	
	STRCPY(pinfo->path, pfile_list->dirpath);
	STRCPY(pinfo->name, item->name);
	
	if( item->size == 0 && item->time == 0 && item->type != F_DIR)
	{
		int 			ret;
		struct stat	file_attribute;
		char			full_path[FULL_PATH_SIZE];
		STRCPY(full_path, pinfo->path);
		strcat(full_path,"/");
		strcat(full_path,pinfo->name);
		ret = fs_stat(full_path, &file_attribute);
		
		if (ret >= 0)
		{
			item ->size = file_attribute.st_size;
			item ->time = file_attribute.st_ctime;			
		}
	}
	pinfo->size = item->size;
	MP_DEBUG("get file: idx=%d\t name=%s\n", index, pinfo->name);

	MP_DEBUG("<<====get_file_from_file_list()\n");
	
	return RET_SUCCESS;
}

/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE rename_file_in_file_list(FileListHandle handle, unsigned int source_file_index, char* new_name)
{
	int										ret;
	char										source_file_path[FULL_PATH_SIZE];
	char										new_file_path[FULL_PATH_SIZE];
	pFileList									pfile_list ;
	pFileListItem								item;
	pFileListItem								new_item;
	struct stat									file_attribute;	

	MP_DEBUG("====>>rename_file_in_file_list()\n");

	pfile_list = (pFileList) handle;
	if ((!new_name) || (!pfile_list) )//|| (source_file_index <= pfile_list->dirnum))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====rename_file_in_file_list()\n");
		return RET_FAILURE;
	}

	item = get_file_list_item_by_index(pfile_list, source_file_index);
	if(item == NULL)
	{
		MP_DEBUG("Invalid source_file_index!\n");
		MP_DEBUG("<<====rename_file_in_file_list()\n");
		return RET_FAILURE;
	}

	STRCPY(source_file_path, pfile_list->dirpath);
	strcat(source_file_path, "/");
	strcat(source_file_path, item->name);

	STRCPY(new_file_path, pfile_list->dirpath);
	strcat(new_file_path, "/");
	strcat(new_file_path, new_name);

	ret = fs_stat(new_file_path, &file_attribute);
	if (ret == 0)
	{
		MP_DEBUG("file exist!\n");
		MP_DEBUG("<<====rename_file_in_file_list()\n");
		return -16;		
	}
	

	ret = fs_rename(source_file_path, new_file_path);
	if (ret <0)
	{
		MP_DEBUG("rename file failed!\n");
		MP_DEBUG("<<====rename_file_in_file_list()\n");
		return RET_FAILURE;
	}
	
	new_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(new_name) + 1);
	if (new_item == NULL)
	{
		MP_DEBUG("malloc file list item failed!\n");
		MP_DEBUG("<<====rename_file_in_file_list()\n");
		return RET_FAILURE;
	}
	
	MEMCPY(new_item, item, sizeof(FileListItem) -1);
	STRCPY(new_item->name, new_name);
	
	ret = fs_stat(new_file_path, &file_attribute);
	if (ret >= 0)
	{
		new_item->size = file_attribute.st_size;
		new_item->time = file_attribute.st_ctime;		
	}
	
	item->listpointer.prev->next = &(new_item->listpointer);
	item->listpointer.next->prev = &(new_item->listpointer);
	FREE(item);
/*	
	if (strcmp(destination_path, pfile_list->dirpath)  == 0)
	{
		//copy to current folder
		if ((pfile_list->dirnum + pfile_list->filenum) < MAX_FILE_NUMBER)
		{
			new_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(item->name) + 1);
			if (new_item == NULL)
			{
				MP_DEBUG("malloc failed!\n");
				MP_DEBUG("<<====rename_file_in_file_list()\n");
				return RET_FAILURE;
			}
			
			MEMSET(new_item, 0, sizeof(FileListItem));

			new_item->type = item->type;
			
			STRCPY(new_item->name, item->name);
			if (new_item->type == F_DIR)
			{
				pfile_list->dirnum++;

				list_add(&item->listpointer, &pfile_list->head);
			}
			else
			{
				pfile_list->filenum++;

				list_add_tail(&item->listpointer, &pfile_list->head);
			}

		}
	}
*/

	fs_sync(new_file_path);
	MP_DEBUG("<<====rename_file_in_file_list()\n");
	
	return RET_SUCCESS;

}

/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE delete_files_from_file_list(FileListHandle handle, unsigned int *index_array, unsigned int index_array_size)
{
	int										ret;
	pFileList									pfile_list ;
	pFileListItem								item;
	struct list_head							*ptr = NULL;
	unsigned int								index = 0;
	pFileListItem								*item_array;
	unsigned int								item_array_size = 0;
	unsigned int								i, j, k, temp;
	char										path[FULL_PATH_SIZE];

	MP_DEBUG("====>>delete_files_from_file_list()\n");	

	pfile_list =(pFileList) handle;
	if ((!index_array)  || (!index_array_size) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====delete_files_from_file_list()\n");
		return RET_FAILURE;
	}

	item_array = MALLOC(MAX_FILE_NUMBER * sizeof(pFileListItem));
	if (!item_array)
	{
		MP_DEBUG("Malloc failed!\n");
		MP_DEBUG("<<====delete_files_from_file_list()\n");
		return RET_FAILURE;
	}
	
	for (i = 0; i < index_array_size; ++i)
	{
		if (index_array[i])
		{
			for (j=0, k=1; j<32; ++j)
			{
				temp = index_array[i] & k;
				if (j < 31)
				{
					k = k*2;
				}
				if (temp)
				{
					index = i * 32 + j + 1;
					item = get_file_list_item_by_index(pfile_list, index);
					if(item)
					{
						item_array[item_array_size] = item;
						item_array_size++;
					}
				}
			}
		}
	}

	for (i = 0; i < item_array_size; ++i)
	{
		STRCPY(path, pfile_list->dirpath);
		strcat(path, "/");
		strcat(path, (item_array[i])->name);
		
		ret = f_rm(path, 4);
		if (ret < 0)
		{
			continue;
		}

		list_del(&((item_array[i])->listpointer));

		if ((item_array[i])->type == F_DIR)
		{
			pfile_list->dirnum--;
		}
		else
		{
			pfile_list->filenum--;
		}
		FREE(item_array[i]);
	}

	FREE(item_array);
	
	MP_DEBUG("<<====delete_files_from_file_list()\n");
	
	return RET_SUCCESS;

}

RET_CODE delete_files_from_file_list_ext(FileListHandle handle, unsigned int *index_array, unsigned int index_array_size,PlayListHandle plst_hdl)
{
	int										ret;
	pFileList									pfile_list ;
	pFileListItem								item;
	struct list_head							*ptr = NULL;
	unsigned int								index = 0;
	pFileListItem								*item_array;
	unsigned int								item_array_size = 0;
	unsigned int								i, j, k, temp;
	char										path[FULL_PATH_SIZE];

	MP_DEBUG("====>>delete_files_from_file_list()\n");	

	pfile_list =(pFileList) handle;
	if ((!index_array)  || (!index_array_size) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====delete_files_from_file_list()\n");
		return RET_FAILURE;
	}

	item_array = MALLOC(MAX_FILE_NUMBER * sizeof(pFileListItem));
	if (!item_array)
	{
		MP_DEBUG("Malloc failed!\n");
		MP_DEBUG("<<====delete_files_from_file_list()\n");
		return RET_FAILURE;
	}
	
	for (i = 0; i < index_array_size; ++i)
	{
		if (index_array[i])
		{
			for (j=0, k=1; j<32; ++j)
			{
				temp = index_array[i] & k;
				if (j < 31)
				{
					k = k*2;
				}
				if (temp)
				{
					index = i * 32 + j + 1;
					item = get_file_list_item_by_index(pfile_list, index);
					if(item)
					{
						item_array[item_array_size] = item;
						item_array_size++;
						if(item->in_play_list >0x00)
						{
							delete_play_list_item(plst_hdl,item->in_play_list+1);
						}
					}
				}
			}
		}
	}

	for (i = 0; i < item_array_size; ++i)
	{
		STRCPY(path, pfile_list->dirpath);
		strcat(path, "/");
		strcat(path, (item_array[i])->name);
		
		ret = f_rm(path, 4);
		if (ret < 0)
		{
			continue;
		}

		list_del(&((item_array[i])->listpointer));

		if ((item_array[i])->type == F_DIR)
		{
			pfile_list->dirnum--;
		}
		else
		{
			pfile_list->filenum--;
		}
		FREE(item_array[i]);
	}

	FREE(item_array);
	
	MP_DEBUG("<<====delete_files_from_file_list()\n");
	
	return RET_SUCCESS;

}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE move_files_from_file_list(FileListHandle handle, unsigned int *index_array, unsigned int index_array_size, char* destination_path)
{
	int										ret;
	pFileList									pfile_list ;
	pFileListItem								item;
	struct list_head							*ptr = NULL;
	unsigned int								index = 0;
	pFileListItem								*item_array;
	unsigned int								item_array_size = 0;
	unsigned int								i, j, k, temp;
	char										path[FULL_PATH_SIZE];

	MP_DEBUG("====>>move_files_from_file_list()\n");

	pfile_list = (pFileList) handle;
	if ((!index_array)  || (!index_array_size) || (!destination_path) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====move_files_from_file_list()\n");
		return RET_FAILURE;
	}

	
	item_array = MALLOC(MAX_FILE_NUMBER * sizeof(pFileListItem));
	if (!item_array)
	{
		MP_DEBUG("Malloc failed!\n");
		MP_DEBUG("<<====move_files_from_file_list()\n");
		return RET_FAILURE;
	}
	

	if (!STRCMP(destination_path, pfile_list->dirpath))
	{
		FREE(item_array);
		MP_DEBUG("<<====move_files_from_file_list()\n");
		return RET_SUCCESS;
	}

	for (i = 0; i < index_array_size; ++i)
	{
		if (index_array[i])
		{
			for (j=0, k=1; j<32; ++j)
			{
				temp = index_array[i] & k;
				if (j < 31)
				{
					k = k*2;
				}
				if (temp)
				{
					index = i * 32 + j + 1;
					item = get_file_list_item_by_index(pfile_list, index);
					if(item)
					{
						item_array[item_array_size] = item;
						item_array_size++;
					}
				}
			}
		}
	}

	for (i = 0; i < item_array_size; ++i)
	{
		STRCPY(path, pfile_list->dirpath);
		strcat(path, "/");
		strcat(path, (item_array[i])->name);
		
		ret = f_mv(path, destination_path, 4);
		if (ret < 0)
		{
			continue;
		}

		list_del(&((item_array[i])->listpointer));

		if ((item_array[i])->type == F_DIR)
		{
			pfile_list->dirnum--;
		}
		else
		{
			pfile_list->filenum--;
		}
		FREE(item_array[i]);
	}

	FREE(item_array);
	
	MP_DEBUG("<<====move_files_from_file_list()\n");
	
	return RET_SUCCESS;
}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE copy_files_from_file_list(FileListHandle handle, unsigned int source_file_index, char* destination_path, int flag, void* callback)
{
	int										ret;
	char										file_path[FULL_PATH_SIZE];
	char										dest_file_path[FULL_PATH_SIZE];
	pFileList									pfile_list ;
	pFileListItem								item;
	pFileListItem								new_item;
	struct stat								file_status;
	
	MP_DEBUG("====>>copy_files_from_file_list()\n");

	pfile_list = (pFileList) handle;
	if ((!destination_path) || (!pfile_list))// || (source_file_index <= pfile_list->dirnum))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====copy_files_from_file_list()\n");
		return RET_FAILURE;
	}

	item = get_file_list_item_by_index(pfile_list, source_file_index);
	if(item == NULL)
	{
		MP_DEBUG("Invalid source_file_index!\n");
		MP_DEBUG("<<====copy_files_from_file_list()\n");
		return RET_FAILURE;
	}

	STRCPY(file_path, pfile_list->dirpath);
	strcat(file_path, "/");
	strcat(file_path, item->name);

	if (!strcasecmp(file_path, destination_path))
	{
		MP_DEBUG("can not copy!\n");
		MP_DEBUG("<<====copy_files_from_file_list()\n");
		return RET_STA_ERR;
	}

	STRCPY(dest_file_path, destination_path);
	strcat(dest_file_path, "/");
	strcat(dest_file_path, item->name);
	if (!strcasecmp(file_path, dest_file_path))
	{
		MP_DEBUG("can not copy!\n");
		MP_DEBUG("<<====copy_files_from_file_list()\n");
		return RET_STA_ERR;
	}

	STRCPY(file_path, destination_path);
	strcat(file_path, "/");
	strcat(file_path, item->name);

	ret = fs_stat(file_path, &file_status);
	if ((ret == 0) && (flag == 4))
	{
		MP_DEBUG("file exist!\n");
		MP_DEBUG("<<====copy_files_from_file_list()\n");
		return -16;		
	}

	STRCPY(file_path, pfile_list->dirpath);
	strcat(file_path, "/");
	strcat(file_path, item->name);

	ret = f_cp(file_path, destination_path, flag, callback);
	if (ret <0)
	{
		MP_DEBUG("copy file failed!\n");
		MP_DEBUG("<<====make_folders_in_file_list()\n");
		return RET_FAILURE;
	}

/*	
	if (strcmp(destination_path, pfile_list->dirpath)  == 0)
	{
		//copy to current folder
		if ((pfile_list->dirnum + pfile_list->filenum) < MAX_FILE_NUMBER)
		{
			new_item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(item->name) + 1);
			if (new_item == NULL)
			{
				MP_DEBUG("malloc failed!\n");
				MP_DEBUG("<<====make_folders_in_file_list()\n");
				return RET_FAILURE;
			}
			
			MEMSET(new_item, 0, sizeof(FileListItem));

			new_item->type = item->type;
			
			STRCPY(new_item->name, item->name);
			if (new_item->type == F_DIR)
			{
				pfile_list->dirnum++;

				list_add(&item->listpointer, &pfile_list->head);
			}
			else
			{
				pfile_list->filenum++;

				list_add_tail(&item->listpointer, &pfile_list->head);
			}

		}
	}
*/

	MP_DEBUG("<<====copy_files_from_file_list()\n");
	
	return RET_SUCCESS;

}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE make_folders_in_file_list(FileListHandle handle, char* folder_name)
{
	int										ret;
	char										path[FULL_PATH_SIZE];
	pFileList									pfile_list ;
	pFileListItem								item;
	struct list_head							*file_list_ptr = NULL, *file_list_ptn = NULL;

	
	MP_DEBUG("====>>make_folders_in_file_list()\n");

	pfile_list = (pFileList) handle;
	if ((!folder_name) || (!pfile_list))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====make_folders_in_file_list()\n");
		return RET_FAILURE;
	}

	list_for_each_safe(file_list_ptr, file_list_ptn, &pfile_list->head)
	{
		item= list_entry(file_list_ptr, FileListItem, listpointer);
		if (!STRCMP(folder_name, item->name))
		{
			MP_DEBUG("The folder which has the same name already exist!\n");
			MP_DEBUG("<<====make_folders_in_file_list()\n");
			return RET_FAILURE;
		}

	}
	
	STRCPY(path, pfile_list->dirpath);
	strcat(path, "/");
	strcat(path, folder_name);
	
	ret = f_mkdir (path, 4);
	if (ret <0)
	{
		MP_DEBUG("make dir failed!\n");
		MP_DEBUG("<<====make_folders_in_file_list()\n");
		return RET_FAILURE;
	}

	if ((pfile_list->dirnum + pfile_list->filenum) < MAX_FILE_NUMBER)
	{
		item = (pFileListItem)MALLOC(sizeof(FileListItem) + STRLEN(folder_name) + 1);
		if (item == NULL)
		{
			MP_DEBUG("malloc failed!\n");
			MP_DEBUG("<<====make_folders_in_file_list()\n");
			return RET_FAILURE;			
		}
		
		MEMSET(item, 0, sizeof(FileListItem));

		item->type = F_DIR;
		
		STRCPY(item->name, folder_name);

		pfile_list->dirnum++;

		list_add(&item->listpointer, &pfile_list->head);

	}

	fs_sync(path);
	MP_DEBUG("<<====make_folders_in_file_list()\n");
	
	return RET_SUCCESS;

}
/////////////////////////////////////////////////////////////////////////////
// file_list_create
//
// Description:
//	Init function
//
// Arguments:
//	None
//	
// Return Value:
//	None
//
/////////////////////////////////////////////////////////////////////////////
RET_CODE 	register_file_list_filter(char *name_array, unsigned int name_array_size)
{
	MP_DEBUG("====>>register_file_list_filter()\n");
	
	if ((!name_array) || (name_array_size <1) || (name_array_size>100))
	{
		MP_DEBUG("Invalid Parameters!\n");
		MP_DEBUG("<<====register_file_list_filters()\n");
		return RET_FAILURE;
	}
	
	//STRCPY( udisk_filter, name);

	MP_DEBUG("<<====register_file_list_filters()\n");
	return RET_SUCCESS;
}
